﻿/***************************************************************
 * 开发人员：网魂小兵@http://www.mozlite.com
 * 
 * 后台线程任务基类。
 * 
 * 最后修改：2011-10-31
 * ************************************************************/
namespace Mozlite.Common
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// 后台线程任务基类。
    /// </summary>
    public abstract class TaskBase
    {
        /// <summary>
        /// 设置一天内的定时执行时间。
        /// </summary>
        /// <param name="hour">小时。</param>
        /// <param name="minute">分钟。</param>
        /// <param name="second">秒钟。</param>
        protected void SetDayExecuteTime(int hour, int minute = 0, int second = 0)
        {
            if (hour > 23)
            {
                hour = 23;
            }
            if (minute > 59)
            {
                minute = 59;
            }
            if (second > 59)
            {
                second = 59;
            }
            this.ExecuteTime = new TimeSpan(hour, minute, second);
        }
        /// <summary>
        /// 设置每个小时定时执行时间。
        /// </summary>
        /// <param name="minutes">分钟。</param>
        /// <param name="seconds">秒钟。</param>
        protected void SetHourExecuteTime(int minutes, int seconds = 0)
        {
            if (minutes > 59)
            {
                minutes = 59;
            }
            if (seconds > 59)
            {
                seconds = 59;
            }
            this.ExecuteTime = new TimeSpan(0, minutes, seconds);
        }
        /// <summary>
        /// 设置每隔多少秒定时执行时间。
        /// </summary>
        /// <param name="seconds">秒钟（最少60秒）。</param>
        protected void SetIntervalExecuteTime(long seconds)
        {
            if (seconds < 60)
                seconds = 60;
            this.ExecuteTime = TimeSpan.FromSeconds(seconds);
        }
        /// <summary>
        /// 设置一月内的定时执行时间。
        /// </summary>
        /// <param name="day">日期。</param>
        /// <param name="hours">小时。</param>
        /// <param name="minutes">分钟。</param>
        /// <param name="seconds">秒钟。</param>
        protected void SetMonthExecuteTime(int day, int hours = 0, int minutes = 0, int seconds = 0)
        {
            if (day > 31)
            {
                day = 31;
            }
            if (hours > 23)
            {
                hours = 23;
            }
            if (minutes > 59)
            {
                minutes = 59;
            }
            if (seconds > 59)
            {
                seconds = 59;
            }
            this.ExecuteTime = new TimeSpan(day, hours, minutes, seconds);
        }
        /// <summary>
        /// 设置每个星期的定时执行时间。
        /// </summary>
        /// <param name="dayOfWeek">星期枚举。</param>
        /// <param name="hours">小时。</param>
        /// <param name="minutes">分钟。</param>
        /// <param name="seconds">秒钟。</param>
        protected void SetWeekExecuteTime(DayOfWeek dayOfWeek, int hours = 0, int minutes = 0, int seconds = 0)
        {
            this.DayOfWeek = dayOfWeek;
            this.SetDayExecuteTime(hours, minutes, seconds);
        }
        /// <summary>
        /// 设置一年内的定时执行时间。
        /// </summary>
        /// <param name="month">月份。</param>
        /// <param name="day">日期。</param>
        /// <param name="hours">小时。</param>
        /// <param name="minutes">分钟。</param>
        /// <param name="seconds">秒钟。</param>
        protected void SetYearExecuteTime(int month, int day = 0, int hours = 0, int minutes = 0, int seconds = 0)
        {
            if (month > 12)
            {
                month = 12;
            }
            if (day > 31)
            {
                day = 31;
            }
            if (hours > 23)
            {
                hours = 23;
            }
            if (minutes > 59)
            {
                minutes = 59;
            }
            if (seconds > 59)
            {
                seconds = 59;
            }
            this.Month = month;
            this.ExecuteTime = new TimeSpan(day, hours, minutes, seconds);
        }
        /// <summary>
        /// 设置执行时间。
        /// </summary>
        protected abstract void SetExecuteTime();
        /// <summary>
        /// 执行行为。
        /// </summary>
        protected abstract void Action();
        internal void Execute()
        {
            if (this.Enabled && IsExecuting())
            {
                try
                {
                    this.Action();
                    this.LastExecuteTime = DateTime.Now;
                    TaskDataProvider.Current.SetLastExecuteTime(this.Type, this.LastExecuteTime);
                }
                catch (Exception ex)
                {
                    Logs.Warn("后台任务服务错误：", "Tasks", EventID.Tasks, ex, "Tasks Action");
                }
            }
        }
        private bool IsExecuting()
        {
            SetExecuteTime();
            DateTime time;
            switch (ExecuteMode)
            {
                case ExecuteMode.Interval:
                    if (this.LastExecuteTime.AddSeconds(this.ExecuteTime.TotalSeconds) > DateTime.Now)
                    {
                        break;
                    }
                    return true;

                case ExecuteMode.Hour:
                    time = new DateTime(this.LastExecuteTime.Year, this.LastExecuteTime.Month, this.LastExecuteTime.Day, this.LastExecuteTime.Hour, this.ExecuteTime.Minutes, this.ExecuteTime.Seconds);
                    if (time.AddHours(1.0) > DateTime.Now)
                    {
                        break;
                    }
                    return true;

                case ExecuteMode.Day:
                    time = new DateTime(this.LastExecuteTime.Year, this.LastExecuteTime.Month, this.LastExecuteTime.Day, this.ExecuteTime.Hours, this.ExecuteTime.Minutes, this.ExecuteTime.Seconds);
                    if (time.AddDays(1.0) > DateTime.Now)
                    {
                        break;
                    }
                    return true;

                case ExecuteMode.Week:
                    if ((DateTime.Now.DayOfWeek == this.DayOfWeek) && (((this.LastExecuteTime.Year != DateTime.Now.Year) || (this.LastExecuteTime.Month != DateTime.Now.Month)) || (this.LastExecuteTime.Day != DateTime.Now.Day)))
                    {
                        time = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, this.ExecuteTime.Hours, this.ExecuteTime.Minutes, this.ExecuteTime.Seconds);
                        if (time <= DateTime.Now)
                        {
                            return true;
                        }
                    }
                    break;

                case ExecuteMode.Month:
                    time = new DateTime(this.LastExecuteTime.Year, this.LastExecuteTime.Month, this.ExecuteTime.Days, this.ExecuteTime.Hours, this.ExecuteTime.Minutes, this.ExecuteTime.Seconds);
                    if (time.AddMonths(1) > DateTime.Now)
                    {
                        break;
                    }
                    return true;

                case ExecuteMode.Year:
                    time = new DateTime(this.LastExecuteTime.Year, this.Month, this.ExecuteTime.Days, this.ExecuteTime.Hours, this.ExecuteTime.Minutes, this.ExecuteTime.Seconds);
                    if (time.AddYears(1) > DateTime.Now)
                    {
                        break;
                    }
                    return true;
            }
            return false;
        }
        /// <summary>
        /// 获取每个星期执行的值。
        /// </summary>
        public DayOfWeek DayOfWeek { get; private set; }
        /// <summary>
        /// 需要重写，判断是否激活。
        /// </summary>
        public abstract bool Enabled { get; }
        /// <summary>
        /// 获取执行刻度。
        /// </summary>
        public TimeSpan ExecuteTime { get; private set; }
        /// <summary>
        /// 获取或设置最后执行时间。
        /// </summary>
        public DateTime LastExecuteTime { get; set; }
        /// <summary>
        /// 获取一年内月份执行时间。
        /// </summary>
        public int Month { get; private set; }
        /// <summary>
        /// 需要重写，获取执行类型，需要和时间设置相对应。
        /// </summary>
        public abstract ExecuteMode ExecuteMode { get; }
        private string type;
        /// <summary>
        /// 任务名称，在程序中这个需要唯一，否则可能出错。
        /// </summary>
        public virtual string Type
        {
            get
            {
                if (type == null)
                    type = this.GetType().Name;
                return type;
            }
        }
    }
}
